import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;

class UserAccount {
    private int accountNumber;
    private String firstName,lastName;
    private double accountBalance;
    private String password;
    
    public UserAccount() {
        
    }
    
    public UserAccount(int n, String f, String l) {
        this.accountNumber = n;
        this.firstName = f;
        this.lastName = l;
        this.accountBalance = 0;
        this.password = "";
    }
    
    public UserAccount(int n, String f, String l, double b) {
        this.accountNumber = n;
        this.firstName = f;
        this.lastName = l;
        this.accountBalance = b;
        this.password = "";
    }
    
    public UserAccount(int n, String f, String l, double b, String p) {
        this.accountNumber = n;
        this.firstName = f;
        this.lastName = l;
        this.accountBalance = b;
        this.password = p;
    }
    
    public double getAccountBalance() {
        return accountBalance;
    }
    
    public int getAccountNumber() {
        return accountNumber;
    }
    
    public String getFirstName() {
        return firstName;
    }
    
    public String getLastName() {
        return lastName;
    }
    
    public String getPassword() {
        return password;
    }
    
    public void setAccountBalance(double accountBalance) {
        this.accountBalance = accountBalance;
    }
    
    public void setAccountNumber(int accountNumber) {
        this.accountNumber = accountNumber;
    }
    
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    public void output() {
        System.out.format("%1$5d %2$-15s %3$-15s %4$10.3f %5$-10s\n",
                accountNumber,
                firstName,
                lastName,
                accountBalance,
                password);
    }
}

class ValidateUserAccount {
    static Class UserAccountClass = null;
    
    public ValidateUserAccount() {
        
    }
    
    static void printFieldInformation(UserAccount obj) {
        Field [] fields = obj.getClass().getFields();
        if(fields == null) {
            System.out.print("The class have no public field");
        } else {
            System.out.print("Public fields of the class");
            for(Field x : fields) {
                System.out.print(x);
            }
        }
    }
    
    static void printMethodInformation(UserAccount obj) {
        Method [] methods = obj.getClass().getMethods();
        if(methods == null) {
            System.out.print("The class have no public method");
        } else {
            System.out.print("Public methods of the class");
            for(Method x : methods) {
                System.out.print(x);
            }
        }
    }
    
    static Object createObject(Constructor constructor, Object[] arguments) {
        Object object = null;
        try {
            object = constructor.newInstance(arguments);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
    
    static Object createObject(Object[] arguments) {
        Object object = null;
        Class [] argTypes = null;
        if(arguments != null) {
            argTypes = new Class[arguments.length];
            for(int i = 0; i < arguments.length; i++) {
                argTypes[i] = arguments[i].getClass();
                if(argTypes[i].getName().equals("java.lang.Integer")) {
                    argTypes[i] = int.class;
                }
                if(argTypes[i].getName().equals("java.lang.Double")) {
                    argTypes[i] = double.class;
                }
            }
        }
        try {
            Constructor constructor = UserAccountClass.getConstructor(argTypes);
            object = constructor.newInstance(arguments);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }
    
    static void setFieldValues(UserAccount obj, String fieldName, Object value) {
        try {
            Field [] fields = obj.getClass().getFields();
            for(Field field : fields) {
                if(field.getName().equals(fieldName)) {
                    setFieldValues(obj, fieldName, value);
                    return;
                }
            }
            Method [] methods = obj.getClass().getMethods();
            for(Method method : methods) {
                if(method.getName().equalsIgnoreCase("set" + fieldName)) {
                    method.invoke(obj, value);
                    return;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    static Object getFieldValue(UserAccount obj, String fieldName) {
        Field [] fields = obj.getClass().getFields();
        try {
            for(Field field : fields) {
                if(field.getName().equals(fieldName)) {
                    return field.get(obj);
                }
            }
            Method [] methods = obj.getClass().getMethods();
            for(Method method : methods) {
                if(method.getName().equalsIgnoreCase("get" + fieldName)) {
                        return method.invoke(obj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static void main(String[] args) {
        try {
            UserAccountClass = Class.forName("UserAccount");
            System.out.println("Creating dynamically an UserAccount object:");
            Class [] paramTypes = new Class []{int.class,
                String.class,
                String.class,
                double.class,
                String.class};
            
            Object [] parameters = new Object []{1, "Tran Quoc", "Ninh", 999.999, "tqninh"};
            Constructor constructor = UserAccountClass.getConstructor(paramTypes);
            UserAccount userAccount1 = (UserAccount)createObject(constructor, parameters);
            userAccount1.output();
            
            parameters = new Object [] {(int)2, "Nguyen Thi", "Ngoan", (double)888.888, "sweetyuuri"};
            UserAccount userAccount2 = (UserAccount)createObject(parameters);
            userAccount2.output();
            
            UserAccount userAccount3 = (UserAccount)createObject(null);
            userAccount3.output();
            setFieldValues(userAccount3, "accountNumber", 10);
            setFieldValues(userAccount3, "firstName", "Le Ngoc");
            setFieldValues(userAccount3, "lastName", "Huong");
            setFieldValues(userAccount3, "accountBalance", 1000.000);
            setFieldValues(userAccount3, "password", "huong1983");
            userAccount3.output();
            System.out.print(getFieldValue(userAccount3, "accountBalance"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}